
from .store import GetGlobalDB
from .lancer import AnyLancer

TEMPTAGPREFIX = "__temp_tag_system_prefix_:"

class AnyTag:

    def __init__(self,entry_id) -> None:
        self.entry_id = entry_id
        self.tag_dict = {}
        self.__load_from_db(entry_id)
    
    def __load_from_db(self,entry_id):
        self.entry_id = entry_id
        self.tag_dict = GetGlobalDB().GetEntryTagDict(entry_id)

    def __store_to_db(self):
        store_keys = set(GetGlobalDB().GetEntryTagDict(self.entry_id).keys())
        now_keys = set(self.tag_dict.keys())
        delete_keys = store_keys - now_keys
        newadd_keys = now_keys - store_keys
        for key in delete_keys:
            if not GetGlobalDB().DelEntryTag(self.entry_id,key):
                print(f"error in DelEntryTag: entry_id={self.entry_id},key={key}")
        for key in newadd_keys:
            value = self.tag_dict[key]
            if not GetGlobalDB().SetEntryTag(self.entry_id,key,value):
                print(f"error in SetEntryTag: entry_id={self.entry_id},key={key}")
        self.tag_dict = GetGlobalDB().GetEntryTagDict(self.entry_id)
    
    def __str__(self) -> str:
        content = ""
        for key,val in self.tag_dict.items():
            content += f"{key}: {val}\n"
        return content

    @staticmethod
    def __to_temptag_name(tag_name:str) -> str:
        return f"{TEMPTAGPREFIX}{tag_name}"
    
    @staticmethod
    def __remove_temp_prefix(tag_name_maybe_temp:str) -> str:
        if tag_name_maybe_temp.startswith(TEMPTAGPREFIX):
            tag_name_maybe_temp = tag_name_maybe_temp.replace(TEMPTAGPREFIX,"")
        return tag_name_maybe_temp
    
    def GetTagDict(self) -> dict:
        tag_dict = { 
            self.__remove_temp_prefix(key) : val for key,val in self.tag_dict.items() 
        }
        return tag_dict
    
    def AddTag(self,tag_name:str,tag_value:str) -> None:
        self.tag_dict[tag_name] = tag_value
        self.__sync_tag_to_db()

    def AddTempTag(self,tag_name:str,tag_value:str) -> None:
        """
        添加临时Tag
        1. 如果tagname已经是正式的tag, 那么正式tag将会删除
        """
        if tag_name in self.tag_dict:
            del self.tag_dict[tag_name]
        tag_name = self.__to_temptag_name(tag_name)
        self.tag_dict[tag_name] = tag_value
        self.__sync_tag_to_db()
    
    def GetTag(self,tag_name:str) -> str:
        """
        对正式tag的查询要优先于临时tag
        """
        if tag_name in self.tag_dict:
            return self.tag_dict[tag_name]
        else:
            temp = self.__to_temptag_name(tag_name)
            if temp in self.tag_dict:
                return self.tag_dict[temp]
        return None
    
    def HasTag(self,tag_name:str) -> bool:
        if tag_name in self.tag_dict:
            return True
        else:
            temp = self.__to_temptag_name(tag_name)
            if temp in self.tag_dict:
                return True
        return False
    
    def ClearTag(self) -> None:
        self.tag_dict = {}
        self.__sync_tag_to_db()
    
    def RemoveTag(self,tag_name:str) -> None:
        temp = self.__to_temptag_name(tag_name)
        if tag_name in self.tag_dict:
            del self.tag_dict[tag_name]
        if temp in self.tag_dict:
            del self.tag_dict[temp]
        self.__sync_tag_to_db()
    
    def RemoveAllTempTag(self) -> None:
        self.tag_dict = {
            key: val for key,val in self.tag_dict.items() 
            if not str(key).startswith(TEMPTAGPREFIX)
        }
        self.__sync_tag_to_db()
    
    def SaveToDB(self):
        self.__store_to_db()

    def __sync_tag_to_db(self):
        self.__store_to_db()
    
    @staticmethod
    def GetEntryIdsOfTag(key:str,value:str=None):
        """
        无论是正式tag还是临时tag, 都将计入
        """
        overall = set()
        idset = GetGlobalDB().GetEntryIdsOfTag(key,value)
        if isinstance(idset,set) and len(idset) > 0:
            overall = overall | idset
        tempkey = AnyTag.__to_temptag_name(key)
        idset = GetGlobalDB().GetEntryIdsOfTag(tempkey,value)
        if isinstance(idset,set) and len(idset) > 0:
            overall = overall | idset
        return overall
    
    @staticmethod
    def TagAll(entry_id_set,key:str,value:str):
        """
        为所有的entry_id打上tag
        """
        for entry_id in entry_id_set:
            if GetGlobalDB().HasEntryId(entry_id):
                tag = AnyTag(entry_id)
                tag.AddTag(key,value)
            else:
                print(f"entry_id {entry_id} not found in database")
    
    @staticmethod
    def ClearSpecTag(entry_id_set,key:str):
        for entry_id in entry_id_set:
            if GetGlobalDB().HasEntryId(entry_id):
                tag = AnyTag(entry_id)
                tag.RemoveTag(key)
            else:
                print(f"entry_id {entry_id} not found in database")


def InitTag(lancer: AnyLancer) -> AnyTag:
    return AnyTag(lancer.get_entry_id())

def GetTag(lancer: AnyLancer) -> AnyTag:
    return AnyTag(lancer.get_entry_id())
